Js内存管理

四种常见的内存泄露

  1. 全局变量
  2. 被遗忘的定时器和回调
  3. 闭包(closure)
  4. 额外的 DOM 引用

# [js数据类型,及内存存储学习笔记]

二 Js中对象的存储问题:

两中类型的特点:
(1)基本类型在内存中占据固定大小的空间,因此被保存在栈内存中。
(2)从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本

(3)引用类型的值是对像,保存在堆内存中,引用类型的值是引用访问的
(4)包含引用类型的值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针
(5)从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象。

(6)用typeof操作符来确定是哪种基本类型,typeof是一个操作符,而不是一个函数,因此typeof后面的圆括号可有可无,用instanceof操作符来确定是哪种引用类型。

栈的优势就是存取速度比堆要快,仅次于直接位于CPU中的寄存器,但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,垃圾收集器会自动地收走这些不再使用的数据,但是缺点是由于在运行时动态分配内存,所以存取速度较慢。

而对于js简单数据类型而言,他们占用内存比较小,如果放在堆中,查找会浪费很多时间,而把堆中的数据放入栈中也会影响栈的效率。比如对象和数组是可以无限拓展的,正好放在可以动态分配大小的堆中。

三 Js中内存管理

Js是一门具有自动垃圾收集机制的编程语言。
Js的垃圾回收机制内容:
(1)离开作用域的值将被自动标记为可以回收,(比如局部变量,在运行完之后,就被自动标记,闭包的时候,属于特殊情况),因此将在垃圾收集期间被删除。
(2)“标记清除”是目前主流的垃圾收集算法,这种算法的思想是给当前不适用的值加上标记,然后在回收其内存。一般这些都是用在全局变量上。
(3)“引用计数”,另一种垃圾收集算法,这种算法的思想是,跟踪记录所有值被引用的次数,该算法在当前的搜索引擎中都不在使用

#1 内存管理

2018.10.16 星期二 16:02 #1

内存生命周期

不管什么程序语言,内存生命周期基本是一致的:
1. 分配你所需要的内存
2. 使用分配到的内存(读、写)
3. 不需要时将其释放\归还
所有语言第二部分都是明确的。第一和第三部分在底层语言中是明确的,但在像JavaScript这些高级语言中,大部分都是隐含的。

JavaScript 的内存分配

#### 值的初始化:
为了不让程序员费心分配内存,JavaScript 在定义变量时就完成了内存分配。

#### 通过函数调用分配内存
有些函数调用结果是分配对象内存:
有些方法分配新变量或者新对象:

使用值

使用值的过程实际上是对分配内存进行读取与写入的操作。读取与写入可能是写入一个变量或者一个对象的属性值,甚至传递函数的参数。

当内存不再需要使用时释放

大多数内存管理的问题都在这个阶段。在这里最艰难的任务是找到“所分配的内存确实已经不再需要了”。它往往要求开发人员来确定在程序中哪一块内存不再需要并且释放它。

高级语言解释器嵌入了“垃圾回收器”,它的主要工作是跟踪内存的分配和使用,以便当分配的内存不再使用时,自动释放它。这只能是一个近似的过程,因为要知道是否仍然需要某块内存是无法判定的(无法通过某种算法解决)。

垃圾回收

如上文所述自动寻找是否一些内存“不再需要”的问题是无法判定的。因此,垃圾回收实现只能有限制的解决一般问题。本节将解释必要的概念,了解主要的垃圾回收算法和它们的局限性。

引用

垃圾回收算法主要依赖于引用的概念。在内存管理的环境中,一个对象如果有访问另一个对象的权限(隐式或者显式),叫做一个对象引用另一个对象。例如,一个Javascript对象具有对它原型的引用(隐式引用)和对它属性的引用(显式引用)。

在这里,“对象”的概念不仅特指 JavaScript 对象,还包括函数作用域(或者全局词法作用域)。

引用计数垃圾收集

这是最初级的垃圾收集算法。此算法把“对象是否不再需要”简化定义为“对象有没有其他对象引用到它”。如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收。

#### 限制:循环引用
该算法有个限制:无法处理循环引用。在下面的例子中,两个对象被创建,并互相引用,形成了一个循环。它们被调用之后会离开函数作用域,所以它们已经没有用了,可以被回收了。然而,引用计数算法考虑到它们互相都有至少一次引用,所以它们不会被回收。

标记-清除算法

这个算法把“对象是否不再需要”简化定义为“对象是否可以获得”。

这个算法假定设置一个叫做根(root)的对象(在Javascript里,根是全局对象)。垃圾回收器将定期从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象……从根开始,垃圾回收器将找到所有可以获得的对象和收集所有不能获得的对象。

这个算法比前一个要好,因为“有零引用的对象”总是不可获得的,但是相反却不一定,参考“循环引用”。

从2012年起,所有现代浏览器都使用了标记-清除垃圾回收算法。所有对JavaScript垃圾回收算法的改进都是基于标记-清除算法的改进,并没有改进标记-清除算法本身和它对“对象是否不再需要”的简化定义。

#### 循环引用不再是问题了
在上面的示例中,函数调用返回之后,两个对象从全局对象出发无法获取。因此,他们将会被垃圾回收器回收。第二个示例同样,一旦 div 和其事件处理无法从根获取到,他们将会被垃圾回收器回收。

#### 限制: 那些无法从根对象查询到的对象都将被清除
尽管这是一个限制,但实践中我们很少会碰到类似的情况,所以开发者不太会去关心垃圾回收机制。

V8 内存分配与垃圾回收

# [V8 内存分配与垃圾回收]
V8 将内存空间主要分为:新生代 和 老生代 两种 。
### 1、新生代空间
新生代空间中的对象为存活时间较短的对象,大多数的对象被分配在这里,这个区域很小但是垃圾回特别频繁 。
它将堆内存一分为二,每一部分空间称为 semispace,其中一个处于使用状态(from 空间),另一个处于闲置状态(to 空间)
新生代的垃圾回收采用 Scavenge 算法 ,其工作原理如下:
### 2、老生代空间
老生代空间中的对象为存活时间长或常驻内存对象,大多数从新生代晋升的对象会被移动到这里。
老生代占用内存较多,如果使用 Scavenge算法,不仅会浪费一半空间,复制如此大块的内存消耗时间将会很长,所以 Scavenge 算法显然不适合。
V8 对于老生代中的垃圾回收,采用 Mark-Sweep (标记清除) 和 Mark-Compact(标记整理) 相结合 。

### 3、三种回收策略比较
### 4、垃圾回收引起的性能问题
为了避免出现 JavaScript 应用逻辑 与 垃圾回收操作 产生不一致的冲突,垃圾回收的三种基本算法都需要将应用逻辑暂停下来,待垃圾回收完成后,再恢复执行应用逻辑,这种行为被称为全停顿 。
为降低全堆垃圾回收而导致的停顿时间,V8 做了以下改善措施:
(1) 限制堆内存大小
(2) 增量式垃圾回收:
V8 后续还引入 Lazy Sweep(延迟清除)、Incremental Compaction (增量式整理),让清理与整理动作也变成增量式的。同时还计划引入并行标记与并行整理,进一步利用多核性能来降低每次停顿的时间。

### 5、垃圾回收的触发条件
作用域: 能形成作用域的函数调用、with 语句 以及 全局作用域。
闭包: V8 无法主动回收内存中的闭包引用和全局变量引用。

### 6、内存泄漏
通常,造成内存泄漏的原因有如下几个:
队列消费不及时
作用域未释放

16:17 #1

# [JavaScript内存优化]

2 JavaScript 的内存回收机制

在V8 中,所有的JavaScript 对象都是通过『堆』来进行内存分配的。

当我们在代码中声明变量并赋值时,V8 就会在堆内存中分配一部分给这个变量。如果已申请的内存不足以存储这个变量时,V8 就会继续申请内存,直到堆的大小达到了V8 的内存上限为止。默认情况下,V8 的堆内存的大小上限在64位系统中为1464MB,在32位系统中则为732MB,即约1.4GB 和0.7GB。

另外,V8 对堆内存中的JavaScript 对象进行分代管理:新生代和老生代。新生代即存活周期较短的JavaScript 对象,如临时变量、字符串等;而老生代则为经过多次垃圾回收仍然存活,存活周期较长的对象,如主控制器、服务器对象等。

垃圾回收算法一直是编程语言的研发中是否重要的​​一环,而V8 中所使用的垃圾回收算法主要有以下几种:
Scavange 算法:通过复制的方式进行内存空间管理,主要用于新生代的内存空间;
Mark-Sweep 算法和Mark-Compact 算法:通过标记来对堆内存进行整理和回收,主要用于老生代对象的检查和回收。

3 优化你的JavaScript

3.1 善用函数

1
2
3
;(function(win, doc, $, undefined) {
// 主业务代码
})(window, document, jQuery);

3.2 绝对不要定义全局变量
3.3 手工解除变量引用
3.4 善用回调
3.5 良好的闭包管理
3.6 内存不是缓存

4 检查JavaScript 的内存使用情况

4.1 Blink / Webkit 浏览器
4.2 Node.js 中的内存检查

其他:

内存术语
chrome 控制台 performance /memory:shallow size, retained size

knowledge is no pay,reward is kindness
0%